/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.mybatis.plugins;

import org.tianyun.cloud.common.dto.CursorPageRequest;
import org.tianyun.cloud.common.dto.PageRequest;
import org.tianyun.cloud.utils.CursorPageBuilder;
import org.tianyun.cloud.utils.PageBuilder;

/**
 * 分页插件帮助类
 *
 * <pre>
 * 示例：
 * PageBuilder<T> pb = PageHelper.startPage(PageRequest);
 * List<T> result = ...;
 * pb.setResult(result);
 * PageResult<T> result = pb.build();
 *
 * </pre>
 *
 * @auther ebert_chan
 */
public class PageHelper {

    private static final ThreadLocal<Context<?>> threadLocal = new ThreadLocal<>();

    /**
     * 开启分页，通过改写sql来实现自动分页
     *
     * @param pageRequest 分页请求参数
     * @return
     * @auther ebert_chan
     */
    public static <T> PageBuilder<T> startPage(PageRequest pageRequest) {
        return startPage(pageRequest.getPageIndex(), pageRequest.getPageSize());
    }

    /**
     * 开启分页，通过改写sql来实现自动分页
     *
     * @param pageIndex 第N页，从1开始
     * @param pageSize  每页显示记录数
     * @return
     * @auther ebert_chan
     */
    public static <T> PageBuilder<T> startPage(int pageIndex, int pageSize) {
        PageBuilder<T> builder = new PageBuilder<>(pageIndex, pageSize);

        Context<T> context = new Context<T>();
        context.setPageBuilder(builder);
        threadLocal.set(context);
        return builder;
    }

    /**
     * 开启分页，上下文中注入分页请求参数，需手动加分页sql语句，mapper.xml中可以直接使用：#{page.offset}, #{page.pageSize}
     *
     * @param cursorPageRequest 分页请求参数
     * @return
     * @auther ebert_chan
     */
    public static <T> CursorPageBuilder<T> startPage(CursorPageRequest cursorPageRequest) {
        return startPage(cursorPageRequest.getPageSize(), cursorPageRequest.getOffset());
    }

    /**
     * 开启分页，上下文中注入分页请求参数，需手动加分页sql语句，mapper.xml中可以直接使用：#{page.offset}, #{page.pageSize}
     *
     * @param pageSize 每页显示记录数
     * @param offset   偏移量
     * @return
     * @auther ebert_chan
     */
    public static <T> CursorPageBuilder<T> startPage(int pageSize, Long offset) {
        CursorPageBuilder<T> builder = new CursorPageBuilder<>(pageSize, offset);

        Context<T> context = new Context<T>();
        context.setCursorPageBuilder(builder);
        threadLocal.set(context);
        return builder;
    }

    public static void clear() {
        threadLocal.remove();
    }

    protected static Context<?> get() {
        return threadLocal.get();
    }

    /**
     * 上下文信息
     *
     * @auther ebert_chan
     */
    public static class Context<T> {

        private PageBuilder<T> pageBuilder;

        private CursorPageBuilder<T> cursorPageBuilder;

        public PageBuilder<T> getPageBuilder() {
            return pageBuilder;
        }

        public void setPageBuilder(PageBuilder<T> pageBuilder) {
            this.pageBuilder = pageBuilder;
        }

        public CursorPageBuilder<T> getCursorPageBuilder() {
            return cursorPageBuilder;
        }

        public void setCursorPageBuilder(CursorPageBuilder<T> cursorPageBuilder) {
            this.cursorPageBuilder = cursorPageBuilder;
        }

    }

}
